using UnityEngine;
using MemoryPack;

namespace Game {
	[MemoryPackable]
	[MemoryPackUnion(0, typeof(BlockItem))]
	[MemoryPackUnion(1, typeof(DebrisItem))]
	[MemoryPackUnion(2, typeof(AmmoItem))]
	public abstract partial class BaseInventoryItem {
		public InventoryItemType ItemType;
		public int Count;

		protected string _nameString;

		public abstract BaseInventoryItem SplitPartToStack(int count);

		public bool CanStack(BaseInventoryItem item) {
			if ( !IsStackable() || !IsEqualKind(item) ) {
				return false;
			}
			var stackSize = CommonStaticData.GetInventoryStackSize(this);
			if ( Count >= stackSize ) {
				return false;
			}
			return true;
		}

		public void AddToStack(BaseInventoryItem item) {
			if ( item == null || item.Count == 0 || item.ItemType != ItemType ) {
				return;
			}
			var stackSize = CommonStaticData.GetInventoryStackSize(this);
			var maxFill = stackSize - Count;
			var addCount = Mathf.Min(maxFill, item.Count);
			Count += addCount;
			item.Count -= addCount;
		}

		public InventoryItemPresenter CreatePresenter() {
			return ItemWorldPresenterPool.Instance?.InventoryItemPresenterFactory(this);
		}

		public int GetSingleItemPrice() {
			return CommonStaticData.GetItemPrice(this);
		}

		public int GetTotalPrice() {
			return GetSingleItemPrice() * Count;
		}

		[MemoryPackIgnore]
		public abstract string ItemName { get; }

		public virtual bool IsEqualKind(BaseInventoryItem item) {
			if ( item == null || item.ItemType != ItemType) {
				return false;
			}
			return true;
		}

		public bool IsStackable() {
			return CommonStaticData.IsInventoryItemStackable(this);
		}
	}

	public abstract partial class BaseInventoryItem<T> : BaseInventoryItem where T : BaseInventoryItem, new() {
		public override bool IsEqualKind(BaseInventoryItem item) {
			if ( !base.IsEqualKind(item) ) {
				return false;
			}
			if ( item.GetType() != typeof(T) ) {
				return false;
			}
			return true;
		}

		public override BaseInventoryItem SplitPartToStack(int count) {
			if ( count == 0 || count >= Count ) {
				return null;
			}

			if ( !CommonStaticData.IsInventoryItemStackable(this) ) {
				return null;
			}

			var newCount = Count - count;
			Count = newCount;
			var newStack = CreateCopy(count);
			return newStack;
		}

		protected virtual T CreateCopy(int count) {
			var copy = new T();
			copy.Count = count;
			return copy;
		}
	}
}
